Specify the tissue of interest, run the boilerplate code which sets up the functions and environment, load the tissue object.

tissue_of_interest = "Pancreas"
library(here)
here() starts at /Users/olgabot/code/tabula-muris
source(here("00_data_ingest", "02_tissue_analysis_rmd", "boilerplate.R"))
Loading required package: ggplot2
package ‘Seurat’ was built under R version 3.4.3Loading required package: cowplot

Attaching package: ‘cowplot’

The following object is masked from ‘package:ggplot2’:

    ggsave

Loading required package: Matrix
package ‘dplyr’ was built under R version 3.4.2package ‘tidyverse’ was built under R version 3.4.2package ‘tidyr’ was built under R version 3.4.2package ‘purrr’ was built under R version 3.4.2
tiss = load_tissue_facs(tissue_of_interest)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
[1] "Scaling data matrix"

  |                                                                                                                                             
  |                                                                                                                                       |   0%
  |                                                                                                                                             
  |=======================================================================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Visualize top genes in principal components

Later on (in FindClusters and TSNE) you will pick a number of principal components to use. This has the effect of keeping the major directions of variation in the data and, ideally, supressing noise. There is no correct answer to the number to use, but a decent rule of thumb is to go until the plot plateaus.

PCElbowPlot(object = tiss)

Choose the number of principal components to use.

# Set number of principal components. 
n.pcs = 12

The clustering is performed based on a nearest neighbors graph. Cells that have similar expression will be joined together. The Louvain algorithm looks for groups of cells with high modularity–more connections within the group than between groups. The resolution parameter determines the scale. Higher resolution will give more clusters, lower resolution will give fewer.

For the top-level clustering, aim to under-cluster instead of over-cluster. It will be easy to subset groups and further analyze them below.

# Set resolution 
res.used <- 0.5
tiss <- FindClusters(object = tiss, reduction.type = "pca", dims.use = 1:n.pcs, 
    resolution = res.used, print.output = 0, save.SNN = TRUE)

We use TSNE solely to visualize the data.

# If cells are too spread out, you can raise the perplexity. If you have few cells, try a lower perplexity (but never less than 10).
tiss <- RunTSNE(object = tiss, dims.use = 1:n.pcs, seed.use = 10, perplexity=30)
TSNEPlot(object = tiss, do.label = T, pt.size = 1.2, label.size = 4)

Check expression of genes useful for indicating cell type. For the islet cells, the mRNA for their specific secretory molecule is a strong signal.

general endocrine: Chga, Isl1 alpha: Gcg, Mafb, Arx, beta: Ins1, Ins2, Mafa, Nkx6-1, Slc2a2, gamma: Ppy delta: Sst, Hhex epsilon: Ghrl ductal: Krt19, Hnf1b immune: Ptprc stellate: Pdgfra, Pdgfrb endothelial: Pecam1, Cdh5, Kdr acinar: Amy2b, Cpa1 other genes of interest: Cpa1, Ptf1a, Neurog3(endocrine progenitor and perhaps adult delta),Pdx1(beta and delta)

Dotplots let you see the intensity of expression and the fraction of cells expressing for each of your genes of interest. The radius shows you the percent of cells in that cluster with at least one read sequenced from that gene. The color level indicates the average Z-score of gene expression for cells in that cluster, where the scaling is done over all cells in the sample.

We can also find all differentially expressed genes marking each cluster. This may take some time.

#clust.markers0 <- FindMarkers(object = tiss, ident.1 = 0, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)
#tiss.markers <- FindAllMarkers(object = tiss, only.pos = TRUE, min.pct = 0.25, thresh.use = 0.25)

Display the top markers you computed above.

#tiss.markers %>% group_by(cluster) %>% top_n(5, avg_logFC)

Using the markers above, we can confidentaly label many of the clusters:

0: beta 3: acinar 4: ductal 6: beta 7: endothelial 8: immune 9: stellate

The abundance of Ppy and Gcg in clusters 1 and 2 makes them seem like mixtures of alpha and gamma cells. The expression of Sst and Hhex in cluster 5 indicates that it might contain many delta cells, but to get a finer resolution, we subset the data and recompute.

We will add those cell_ontology_class to the dataset.

tiss <- StashIdent(object = tiss, save.name = "cluster.ids")
cluster.ids <- c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
free_annotation <- c(
  "beta cell", 
   NA, 
   NA, 
   "acinar cell", 
   "ductal cell", 
   NA,
   "beta cell", 
   "endothelial cell", 
   "immune cell", 
   "stellate cell")
cell_ontology_class <-c(
  "type B pancreatic cell", 
   NA, 
   NA, 
   "pancreatic acinar cell", 
   "pancreatic ductal cell", 
   NA, 
   "type B pancreatic cell", 
   "endothelial cell", 
   "leukocyte", 
   "pancreatic stellate cell")
validate_cell_ontology(cell_ontology_class)
cell_ontology_id = convert_to_cell_ontology_id(cell_ontology_class)
tiss@meta.data['free_annotation'] <- as.character(plyr::mapvalues(x = tiss@ident, from = cluster.ids, to = free_annotation))
validate_cell_ontology(cell_ontology_class)
cell_ontology_id = convert_to_cell_ontology_id(cell_ontology_class)
tiss@meta.data['cell_ontology_class'] <- as.character(plyr::mapvalues(x = tiss@ident, from = cluster.ids, to = cell_ontology_class))
tiss@meta.data['cell_ontology_id'] <- as.character(plyr::mapvalues(x = tiss@ident, from = cluster.ids, to = cell_ontology_id))

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = tiss, do.return = TRUE, group.by = "plate.barcode")

Subcluster

subtiss = SubsetData(tiss, ident.use = c(1,2,5))
subtiss <- subtiss %>% ScaleData() %>% 
  FindVariableGenes(do.plot = TRUE, x.high.cutoff = Inf, y.cutoff = 0.5) %>%
  RunPCA(do.print = FALSE)
[1] "Scaling data matrix"

  |                                                                                                                                             
  |                                                                                                                                       |   0%
  |                                                                                                                                             
  |=======================================================================================================================================| 100%
Calculating gene means
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating gene variance to mean ratios
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

PCHeatmap(object = subtiss, pc.use = 1:3, cells.use = 500, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)

PCElbowPlot(subtiss)

sub.n.pcs = 8
sub.res.use = 1
subtiss <- subtiss %>% FindClusters(reduction.type = "pca", dims.use = 1:sub.n.pcs, 
    resolution = sub.res.use, print.output = 0, save.SNN = TRUE) %>%
    RunTSNE(dims.use = 1:sub.n.pcs, seed.use = 10, perplexity=30)
TSNEPlot(object = subtiss, do.label = T, pt.size = 1.2, label.size = 4)

All cells have the same value of Ptf1a.

VlnPlot(subtiss, 'Ppy')

table(subtiss@ident)

  0   1   2   3   4   5   6   7 
128 103  86  79  73  61  40  33 

Discover new PP marker genes (negative or positive)

gamma_markers = FindMarkers(subtiss, ident.1 = c(6,7), ident.2 = c(0,1,2,4), test.use = "roc")

   |                                                  | 0 % ~calculating  
   |+                                                 | 1 % ~48s          
   |+                                                 | 2 % ~52s          
   |++                                                | 3 % ~52s          
   |++                                                | 4 % ~51s          
   |+++                                               | 5 % ~52s          
   |+++                                               | 6 % ~51s          
   |++++                                              | 7 % ~50s          
   |++++                                              | 8 % ~50s          
   |+++++                                             | 9 % ~49s          
   |+++++                                             | 10% ~48s          
   |++++++                                            | 11% ~47s          
   |++++++                                            | 12% ~46s          
   |+++++++                                           | 13% ~46s          
   |+++++++                                           | 14% ~45s          
   |++++++++                                          | 15% ~45s          
   |++++++++                                          | 16% ~45s          
   |+++++++++                                         | 17% ~44s          
   |+++++++++                                         | 18% ~43s          
   |++++++++++                                        | 19% ~42s          
   |++++++++++                                        | 20% ~42s          
   |+++++++++++                                       | 21% ~41s          
   |+++++++++++                                       | 22% ~40s          
   |++++++++++++                                      | 23% ~40s          
   |++++++++++++                                      | 24% ~39s          
   |+++++++++++++                                     | 25% ~38s          
   |+++++++++++++                                     | 26% ~38s          
   |++++++++++++++                                    | 27% ~37s          
   |++++++++++++++                                    | 28% ~37s          
   |+++++++++++++++                                   | 29% ~36s          
   |+++++++++++++++                                   | 30% ~36s          
   |++++++++++++++++                                  | 31% ~35s          
   |++++++++++++++++                                  | 32% ~34s          
   |+++++++++++++++++                                 | 33% ~34s          
   |+++++++++++++++++                                | 34% ~34s          
   |++++++++++++++++++                                | 35% ~33s          
   |++++++++++++++++++                                | 36% ~33s          
   |+++++++++++++++++++                               | 37% ~32s          
   |+++++++++++++++++++                               | 38% ~31s          
   |++++++++++++++++++++                              | 39% ~31s          
   |++++++++++++++++++++                              | 40% ~30s          
   |+++++++++++++++++++++                             | 41% ~30s          
   |+++++++++++++++++++++                             | 42% ~29s          
   |++++++++++++++++++++++                            | 43% ~29s          
   |++++++++++++++++++++++                            | 44% ~28s          
   |+++++++++++++++++++++++                           | 45% ~28s          
   |+++++++++++++++++++++++                           | 46% ~27s          
   |++++++++++++++++++++++++                          | 47% ~27s          
   |++++++++++++++++++++++++                          | 48% ~26s          
   |+++++++++++++++++++++++++                         | 49% ~26s          
   |+++++++++++++++++++++++++                         | 50% ~25s          
   |++++++++++++++++++++++++++                        | 51% ~25s          
   |++++++++++++++++++++++++++                        | 52% ~24s          
   |+++++++++++++++++++++++++++                       | 53% ~24s          
   |+++++++++++++++++++++++++++                       | 54% ~23s          
   |++++++++++++++++++++++++++++                      | 55% ~23s          
   |++++++++++++++++++++++++++++                     | 56% ~22s          
   |+++++++++++++++++++++++++++++                     | 57% ~22s          
   |+++++++++++++++++++++++++++++                     | 58% ~21s          
   |++++++++++++++++++++++++++++++                    | 59% ~21s          
   |++++++++++++++++++++++++++++++                    | 60% ~20s          
   |+++++++++++++++++++++++++++++++                   | 61% ~20s          
   |+++++++++++++++++++++++++++++++                   | 62% ~19s          
   |++++++++++++++++++++++++++++++++                  | 63% ~19s          
   |++++++++++++++++++++++++++++++++                  | 64% ~18s          
   |+++++++++++++++++++++++++++++++++                 | 65% ~18s          
   |+++++++++++++++++++++++++++++++++                 | 66% ~17s          
   |++++++++++++++++++++++++++++++++++                | 67% ~17s          
   |++++++++++++++++++++++++++++++++++               | 68% ~16s          
   |+++++++++++++++++++++++++++++++++++               | 69% ~16s          
   |+++++++++++++++++++++++++++++++++++               | 70% ~15s          
   |++++++++++++++++++++++++++++++++++++              | 71% ~15s          
   |++++++++++++++++++++++++++++++++++++              | 72% ~14s          
   |+++++++++++++++++++++++++++++++++++++             | 73% ~14s          
   |+++++++++++++++++++++++++++++++++++++             | 74% ~13s          
   |++++++++++++++++++++++++++++++++++++++            | 75% ~13s          
   |++++++++++++++++++++++++++++++++++++++            | 76% ~12s          
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~12s          
   |+++++++++++++++++++++++++++++++++++++++          | 78% ~11s          
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~11s          
   |++++++++++++++++++++++++++++++++++++++++         | 80% ~10s          
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~10s          
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~09s          
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~09s          
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~08s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~08s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~07s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~07s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~06s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~06s          
   |+++++++++++++++++++++++++++++++++++++++++++++    | 90% ~05s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~05s          
   |++++++++++++++++++++++++++++++++++++++++++++++   | 92% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~03s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~02s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 51s
gamma_markers = FindMarkers(subtiss, ident.1 = c(6,7), ident.2 = c(0,1,2,4), test.use = "wilcox")

   |                                                  | 0 % ~calculating  
   |+                                                 | 1 % ~01m 29s      
   |+                                                 | 2 % ~01m 27s      
   |++                                                | 3 % ~01m 27s      
   |++                                                | 4 % ~01m 24s      
   |+++                                               | 5 % ~01m 23s      
   |+++                                               | 6 % ~01m 23s      
   |++++                                              | 7 % ~01m 22s      
   |++++                                              | 8 % ~01m 20s      
   |+++++                                             | 9 % ~01m 20s      
   |+++++                                             | 10% ~01m 20s      
   |++++++                                            | 11% ~01m 19s      
   |++++++                                            | 12% ~01m 18s      
   |+++++++                                           | 13% ~01m 17s      
   |+++++++                                           | 14% ~01m 16s      
   |++++++++                                          | 15% ~01m 15s      
   |++++++++                                          | 16% ~01m 14s      
   |+++++++++                                         | 17% ~01m 14s      
   |+++++++++                                         | 18% ~01m 13s      
   |++++++++++                                        | 19% ~01m 12s      
   |++++++++++                                        | 20% ~01m 12s      
   |+++++++++++                                       | 21% ~01m 11s      
   |+++++++++++                                       | 22% ~01m 10s      
   |++++++++++++                                      | 23% ~01m 09s      
   |++++++++++++                                      | 24% ~01m 08s      
   |+++++++++++++                                     | 25% ~01m 07s      
   |+++++++++++++                                     | 26% ~01m 06s      
   |++++++++++++++                                    | 27% ~01m 05s      
   |++++++++++++++                                    | 28% ~01m 04s      
   |+++++++++++++++                                   | 29% ~01m 03s      
   |+++++++++++++++                                   | 30% ~01m 03s      
   |++++++++++++++++                                  | 31% ~01m 02s      
   |++++++++++++++++                                  | 32% ~01m 01s      
   |+++++++++++++++++                                 | 33% ~01m 00s      
   |+++++++++++++++++                                | 34% ~59s          
   |++++++++++++++++++                                | 35% ~59s          
   |++++++++++++++++++                                | 36% ~58s          
   |+++++++++++++++++++                               | 37% ~57s          
   |+++++++++++++++++++                               | 38% ~56s          
   |++++++++++++++++++++                              | 39% ~55s          
   |++++++++++++++++++++                              | 40% ~54s          
   |+++++++++++++++++++++                             | 41% ~53s          
   |+++++++++++++++++++++                             | 42% ~52s          
   |++++++++++++++++++++++                            | 43% ~51s          
   |++++++++++++++++++++++                            | 44% ~51s          
   |+++++++++++++++++++++++                           | 45% ~50s          
   |+++++++++++++++++++++++                           | 46% ~49s          
   |++++++++++++++++++++++++                          | 47% ~48s          
   |++++++++++++++++++++++++                          | 48% ~47s          
   |+++++++++++++++++++++++++                         | 49% ~46s          
   |+++++++++++++++++++++++++                         | 50% ~45s          
   |++++++++++++++++++++++++++                        | 51% ~44s          
   |++++++++++++++++++++++++++                        | 52% ~44s          
   |+++++++++++++++++++++++++++                       | 53% ~43s          
   |+++++++++++++++++++++++++++                       | 54% ~42s          
   |++++++++++++++++++++++++++++                      | 55% ~41s          
   |++++++++++++++++++++++++++++                     | 56% ~40s          
   |+++++++++++++++++++++++++++++                     | 57% ~39s          
   |+++++++++++++++++++++++++++++                     | 58% ~38s          
   |++++++++++++++++++++++++++++++                    | 59% ~37s          
   |++++++++++++++++++++++++++++++                    | 60% ~36s          
   |+++++++++++++++++++++++++++++++                   | 61% ~35s          
   |+++++++++++++++++++++++++++++++                   | 62% ~35s          
   |++++++++++++++++++++++++++++++++                  | 63% ~34s          
   |++++++++++++++++++++++++++++++++                  | 64% ~33s          
   |+++++++++++++++++++++++++++++++++                 | 65% ~32s          
   |+++++++++++++++++++++++++++++++++                 | 66% ~31s          
   |++++++++++++++++++++++++++++++++++                | 67% ~30s          
   |++++++++++++++++++++++++++++++++++               | 68% ~29s          
   |+++++++++++++++++++++++++++++++++++               | 69% ~28s          
   |+++++++++++++++++++++++++++++++++++               | 70% ~27s          
   |++++++++++++++++++++++++++++++++++++              | 71% ~26s          
   |++++++++++++++++++++++++++++++++++++              | 72% ~26s          
   |+++++++++++++++++++++++++++++++++++++             | 73% ~25s          
   |+++++++++++++++++++++++++++++++++++++             | 74% ~24s          
   |++++++++++++++++++++++++++++++++++++++            | 75% ~23s          
   |++++++++++++++++++++++++++++++++++++++            | 76% ~22s          
   |+++++++++++++++++++++++++++++++++++++++           | 77% ~21s          
   |+++++++++++++++++++++++++++++++++++++++          | 78% ~20s          
   |++++++++++++++++++++++++++++++++++++++++          | 79% ~19s          
   |++++++++++++++++++++++++++++++++++++++++         | 80% ~18s          
   |+++++++++++++++++++++++++++++++++++++++++         | 81% ~18s          
   |+++++++++++++++++++++++++++++++++++++++++         | 82% ~17s          
   |++++++++++++++++++++++++++++++++++++++++++        | 83% ~16s          
   |++++++++++++++++++++++++++++++++++++++++++        | 84% ~15s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 85% ~14s          
   |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~13s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~12s          
   |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~11s          
   |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~10s          
   |+++++++++++++++++++++++++++++++++++++++++++++    | 90% ~09s          
   |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~08s          
   |++++++++++++++++++++++++++++++++++++++++++++++   | 92% ~07s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~06s          
   |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~06s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 95% ~05s          
   |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~04s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~03s          
   |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~02s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~01s          
   |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 01m 32s

New markers from this test include 1) negative marker genes, aka. those abscent in PP cells or highly abundant in alpha cells ‘Arg1’, ‘Mafb’, ‘Gfra3’, ‘Slc38a5’, ‘Dpp10’,‘Ang’,‘Irx1’, 2) positive marker genes, aka. those abscent in alpha cells or highly abundant in PP cells ‘Cd9’, ‘Spp1’, ‘Tspan8’, ‘Folr1’,‘Vsig1’

gamma_genes_to_check_neg = c('Arg1', 'Mafb', 'Gfra3', 'Slc38a5', 'Dpp10','Ang','Irx1')
gamma_genes_to_check_pos = c('Cd9', 'Spp1', 'Tspan8', 'Folr1','Vsig1')

DotPlot(subtiss, gamma_genes_to_check_neg, col.max = 2.5, plot.legend = T, do.return = T) + coord_flip()

DotPlot(subtiss, gamma_genes_to_check_pos, col.max = 2.5, plot.legend = T, do.return = T) + coord_flip()

From these genes, it appears that the clusters represent:

0: alpha 1: alpha 2: alpha 3: delta 4: alpha 5: delta 6: gamma 7: gamma

The multitude of clusters of each type correspond mostly to individual animals/sexes.

table(FetchData(subtiss, c('mouse.id','ident')) %>% droplevels())
        ident
mouse.id   0   1   2   3   4   5   6   7
  3_10_M 113   8   1  29   0  12  10   1
  3_38_F   4  14  82   4   0  21   0  11
  3_39_F   2  80   3   2   0  19   0  21
  3_8_M    9   1   0  44  73   9  30   0
sub.cluster.ids <- c(0, 1, 2, 3, 4, 5, 6, 7)
sub.free_annotation <- c("pancreatic A cell", "pancreatic A cell", "pancreatic A cell", "pancreatic D cell", "pancreatic A cell", "pancreatic D cell", "pancreatic PP cell", "pancreatic PP cell")
sub.cell_ontology_class <-c("pancreatic A cell", "pancreatic A cell", "pancreatic A cell", "pancreatic D cell", "pancreatic A cell", "pancreatic D cell", "pancreatic PP cell", "pancreatic PP cell")
validate_cell_ontology(sub.cell_ontology_class)
sub.cell_ontology_id = convert_to_cell_ontology_id(sub.cell_ontology_class)
subtiss@meta.data['free_annotation'] <- as.character(plyr::mapvalues(x = subtiss@ident, from = sub.cluster.ids, to = sub.free_annotation))
validate_cell_ontology(sub.cell_ontology_class)
sub.cell_ontology_id = convert_to_cell_ontology_id(sub.cell_ontology_class)
subtiss@meta.data['free_annotation'] <- as.character(plyr::mapvalues(x = subtiss@ident, from = sub.cluster.ids, to = sub.free_annotation))
subtiss@meta.data['cell_ontology_class'] <- as.character(plyr::mapvalues(x = subtiss@ident, from = sub.cluster.ids, to = sub.cell_ontology_class))
subtiss@meta.data['cell_ontology_id'] <- as.character(plyr::mapvalues(x = subtiss@ident, from = sub.cluster.ids, to = sub.cell_ontology_id))

Add subcluster cell_ontology_class to main cell_ontology_class

sub.cells = rownames(subtiss@meta.data)
tiss@meta.data[sub.cells, 'free_annotation'] = subtiss@meta.data[,'free_annotation']
tiss@meta.data[sub.cells, 'cell_ontology_class'] = subtiss@meta.data[,'cell_ontology_class']
tiss@meta.data[sub.cells, 'cell_ontology_id'] = subtiss@meta.data[,'cell_ontology_id']

Checking for batch effects

Color by metadata, like plate barcode, to check for batch effects.

TSNEPlot(object = tiss, do.return = TRUE, group.by = "plate.barcode")

Final coloring

Color by cell ontology class on the original TSNE.

TSNEPlot(object = tiss, do.return = TRUE, group.by = "cell_ontology_class")

table(tiss@meta.data[["cell_ontology_class"]])

        endothelial cell                leukocyte        pancreatic A cell   pancreatic acinar cell        pancreatic D cell 
                      66                       54                      390                      182                      140 
  pancreatic ductal cell       pancreatic PP cell pancreatic stellate cell   type B pancreatic cell 
                     161                       73                       49                      449 

Save the Robject for later

filename = here('00_data_ingest', '04_tissue_robj_generated', 
                     paste0("facs_", tissue_of_interest, "_seurat_tiss.Robj"))
print(filename)
[1] "/Users/olgabot/code/tabula-muris/00_data_ingest/04_tissue_robj_generated/facs_Pancreas_seurat_tiss.Robj"
save(tiss, file=filename)
# To reload a saved object
# filename = here('00_data_ingest', '04_tissue_robj_generated', 
#                      paste0("facs_", tissue_of_interest, "_seurat_tiss.Robj"))
# load(file=filename)

Add column for Neurog3 expression for supplemental figures

tiss@meta.data[, 'Neurog3>0_scaled'] = tiss@scale.data['Neurog3', ] > 0
tiss@meta.data[, 'Neurog3>0_raw'] = tiss@raw.data['Neurog3', colnames(tiss@scale.data)] > 0
Error in `[<-.data.frame`(`*tmp*`, , "Neurog3>0_raw", value = c(FALSE,  : 
  replacement has 1 row, data has 1564

Export the final metadata

So that Biohub can easily combine all your cell_ontology_class, please export them as a simple csv.

head(tiss@meta.data)
filename = here('00_data_ingest', '03_tissue_annotation_csv', 
                     paste0(tissue_of_interest, "_annotation.csv"))
write.csv(FetchData(tiss, c('plate.barcode','cell_ontology_class','cell_ontology_id', 'free_annotation', 'tSNE_1', 'tSNE_2')), file=filename)

Explore Ppy+ multihormonal cells (to be continued)

FetchData(subtiss, c('Ppy', 'Gcg', 'Arx', 'Irx2', 'Mafb', 'mouse.id', 'plate.barcode', 'ident')) %>% 
  ggplot(aes(x = Ppy, y = Gcg, color = plate.barcode)) + geom_point()
# It would be interesting to fetch the ids of these cells expressing high Gcg as well as Ppy, and examine their genetic signature.
gammatiss <- RunPCA(subtiss, pc.genes = c('Arg1', 'Mafb', 'Gfra3', 'Slc38a5', 'Dpp10','Ang','Irx1', 'Cd9', 'Spp1', 'Tspan8', 'Folr1','Vsig1'), pcs.compute = 3)
PCHeatmap(object = gammatiss, pc.use = 1:3, cells.use = 500, do.balanced = TRUE, label.columns = FALSE, num.genes = 8)
GenePlot(subtiss, 'Vsig1', 'Gfra3')

Write the cell ontology and free annotations to CSV.

save_annotation_csv(tiss, tissue_of_interest, "facs", additional_cols = additional_cols)
Error in FetchData(tiss, columns) : Error: Neurog3>0_raw not found
LS0tCnRpdGxlOiAiUGFuY3JlYXMgRkFDUyBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKU3BlY2lmeSB0aGUgdGlzc3VlIG9mIGludGVyZXN0LCBydW4gdGhlIGJvaWxlcnBsYXRlIGNvZGUgd2hpY2ggc2V0cyB1cCB0aGUgZnVuY3Rpb25zIGFuZCBlbnZpcm9ubWVudCwgbG9hZCB0aGUgdGlzc3VlIG9iamVjdC4KCmBgYHtyfQp0aXNzdWVfb2ZfaW50ZXJlc3QgPSAiUGFuY3JlYXMiCgpsaWJyYXJ5KGhlcmUpCnNvdXJjZShoZXJlKCIwMF9kYXRhX2luZ2VzdCIsICIwMl90aXNzdWVfYW5hbHlzaXNfcm1kIiwgImJvaWxlcnBsYXRlLlIiKSkKdGlzcyA9IGxvYWRfdGlzc3VlX2ZhY3ModGlzc3VlX29mX2ludGVyZXN0KQpgYGAKClZpc3VhbGl6ZSB0b3AgZ2VuZXMgaW4gcHJpbmNpcGFsIGNvbXBvbmVudHMKCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NCwgZmlnLndpZHRoPTh9ClBDSGVhdG1hcChvYmplY3QgPSB0aXNzLCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDUwMCwgZG8uYmFsYW5jZWQgPSBUUlVFLCBsYWJlbC5jb2x1bW5zID0gRkFMU0UsIG51bS5nZW5lcyA9IDgpCmBgYAoKTGF0ZXIgb24gKGluIEZpbmRDbHVzdGVycyBhbmQgVFNORSkgeW91IHdpbGwgcGljayBhIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuIFRoaXMgaGFzIHRoZSBlZmZlY3Qgb2Yga2VlcGluZyB0aGUgbWFqb3IgZGlyZWN0aW9ucyBvZiB2YXJpYXRpb24gaW4gdGhlIGRhdGEgYW5kLCBpZGVhbGx5LCBzdXByZXNzaW5nIG5vaXNlLiBUaGVyZSBpcyBubyBjb3JyZWN0IGFuc3dlciB0byB0aGUgbnVtYmVyIHRvIHVzZSwgYnV0IGEgZGVjZW50IHJ1bGUgb2YgdGh1bWIgaXMgdG8gZ28gdW50aWwgdGhlIHBsb3QgcGxhdGVhdXMuCgpgYGB7cn0KUENFbGJvd1Bsb3Qob2JqZWN0ID0gdGlzcykKYGBgCgpDaG9vc2UgdGhlIG51bWJlciBvZiBwcmluY2lwYWwgY29tcG9uZW50cyB0byB1c2UuCmBgYHtyfQojIFNldCBudW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHMuIApuLnBjcyA9IDEyCmBgYAoKClRoZSBjbHVzdGVyaW5nIGlzIHBlcmZvcm1lZCBiYXNlZCBvbiBhIG5lYXJlc3QgbmVpZ2hib3JzIGdyYXBoLiBDZWxscyB0aGF0IGhhdmUgc2ltaWxhciBleHByZXNzaW9uIHdpbGwgYmUgam9pbmVkIHRvZ2V0aGVyLiBUaGUgTG91dmFpbiBhbGdvcml0aG0gbG9va3MgZm9yIGdyb3VwcyBvZiBjZWxscyB3aXRoIGhpZ2ggbW9kdWxhcml0eS0tbW9yZSBjb25uZWN0aW9ucyB3aXRoaW4gdGhlIGdyb3VwIHRoYW4gYmV0d2VlbiBncm91cHMuIFRoZSByZXNvbHV0aW9uIHBhcmFtZXRlciBkZXRlcm1pbmVzIHRoZSBzY2FsZS4gSGlnaGVyIHJlc29sdXRpb24gd2lsbCBnaXZlIG1vcmUgY2x1c3RlcnMsIGxvd2VyIHJlc29sdXRpb24gd2lsbCBnaXZlIGZld2VyLgoKRm9yIHRoZSB0b3AtbGV2ZWwgY2x1c3RlcmluZywgYWltIHRvIHVuZGVyLWNsdXN0ZXIgaW5zdGVhZCBvZiBvdmVyLWNsdXN0ZXIuIEl0IHdpbGwgYmUgZWFzeSB0byBzdWJzZXQgZ3JvdXBzIGFuZCBmdXJ0aGVyIGFuYWx5emUgdGhlbSBiZWxvdy4KCmBgYHtyfQojIFNldCByZXNvbHV0aW9uIApyZXMudXNlZCA8LSAwLjUKCnRpc3MgPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IHRpc3MsIHJlZHVjdGlvbi50eXBlID0gInBjYSIsIGRpbXMudXNlID0gMTpuLnBjcywgCiAgICByZXNvbHV0aW9uID0gcmVzLnVzZWQsIHByaW50Lm91dHB1dCA9IDAsIHNhdmUuU05OID0gVFJVRSkKYGBgCgpXZSB1c2UgVFNORSBzb2xlbHkgdG8gdmlzdWFsaXplIHRoZSBkYXRhLgoKYGBge3J9CiMgSWYgY2VsbHMgYXJlIHRvbyBzcHJlYWQgb3V0LCB5b3UgY2FuIHJhaXNlIHRoZSBwZXJwbGV4aXR5LiBJZiB5b3UgaGF2ZSBmZXcgY2VsbHMsIHRyeSBhIGxvd2VyIHBlcnBsZXhpdHkgKGJ1dCBuZXZlciBsZXNzIHRoYW4gMTApLgp0aXNzIDwtIFJ1blRTTkUob2JqZWN0ID0gdGlzcywgZGltcy51c2UgPSAxOm4ucGNzLCBzZWVkLnVzZSA9IDEwLCBwZXJwbGV4aXR5PTMwKQpgYGAKCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSB0aXNzLCBkby5sYWJlbCA9IFQsIHB0LnNpemUgPSAxLjIsIGxhYmVsLnNpemUgPSA0KQpgYGAKCkNoZWNrIGV4cHJlc3Npb24gb2YgZ2VuZXMgdXNlZnVsIGZvciBpbmRpY2F0aW5nIGNlbGwgdHlwZS4gRm9yIHRoZSBpc2xldCBjZWxscywgdGhlIG1STkEgZm9yIHRoZWlyIHNwZWNpZmljIHNlY3JldG9yeSBtb2xlY3VsZSBpcyBhIHN0cm9uZyBzaWduYWwuCgpnZW5lcmFsIGVuZG9jcmluZTogQ2hnYSwgSXNsMQphbHBoYTogR2NnLCBNYWZiLCBBcngsIApiZXRhOiBJbnMxLCBJbnMyLCBNYWZhLCBOa3g2LTEsIFNsYzJhMiwgCmdhbW1hOiBQcHkKZGVsdGE6IFNzdCwgSGhleAplcHNpbG9uOiBHaHJsCmR1Y3RhbDogS3J0MTksIEhuZjFiCmltbXVuZTogUHRwcmMKc3RlbGxhdGU6IFBkZ2ZyYSwgUGRnZnJiCmVuZG90aGVsaWFsOiBQZWNhbTEsIENkaDUsIEtkcgphY2luYXI6IEFteTJiLCBDcGExCm90aGVyIGdlbmVzIG9mIGludGVyZXN0OiBDcGExLCBQdGYxYSwgTmV1cm9nMyhlbmRvY3JpbmUgcHJvZ2VuaXRvciBhbmQgcGVyaGFwcyBhZHVsdCBkZWx0YSksUGR4MShiZXRhIGFuZCBkZWx0YSkKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CmdlbmVzX3RvX2NoZWNrID0gYygnQ2hnYScsICdJc2wxJywgJ0djZycsICdNYWZiJywgJ0FyeCcsICdJbnMxJywgJ0luczInLCAnTWFmYScsICdOa3g2LTEnLCAnU2xjMmEyJywgJ1NzdCcsICdIaGV4JywgJ1BkeDEnLCAnUHB5JywnR2hybCcsICdLcnQxOScsICdIbmYxYicsICdBbXkyYicsICdDcGExJywgJ1B0ZjFhJywgJ1BkZ2ZyYScsICdQZGdmcmInLCAnUGVjYW0xJywgJ0NkaDUnLCAnS2RyJywnUHRwcmMnLCAnTmV1cm9nMycpCkZlYXR1cmVQbG90KHRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwdC5zaXplID0gMSwgbkNvbCA9IDUsIGNvbHMudXNlID0gYygiZ3JleSIsICJibHVlIikpCmBgYAoKRG90cGxvdHMgbGV0IHlvdSBzZWUgdGhlIGludGVuc2l0eSBvZiBleHByZXNzaW9uIGFuZCB0aGUgZnJhY3Rpb24gb2YgY2VsbHMgZXhwcmVzc2luZyBmb3IgZWFjaCBvZiB5b3VyIGdlbmVzIG9mIGludGVyZXN0LgpUaGUgcmFkaXVzIHNob3dzIHlvdSB0aGUgcGVyY2VudCBvZiBjZWxscyBpbiB0aGF0IGNsdXN0ZXIgd2l0aCBhdCBsZWFzdCBvbmUgcmVhZCBzZXF1ZW5jZWQgZnJvbSB0aGF0IGdlbmUuIFRoZSBjb2xvciBsZXZlbCBpbmRpY2F0ZXMgdGhlIGF2ZXJhZ2UgWi1zY29yZSBvZiBnZW5lIGV4cHJlc3Npb24gZm9yIGNlbGxzIGluIHRoYXQgY2x1c3Rlciwgd2hlcmUgdGhlIHNjYWxpbmcgaXMgZG9uZSBvdmVyIGFsbCBjZWxscyBpbiB0aGUgc2FtcGxlLgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQpEb3RQbG90KHRpc3MsIGdlbmVzX3RvX2NoZWNrLCBwbG90LmxlZ2VuZCA9IFQsIGNvbC5tYXggPSAyLjUsIGRvLnJldHVybiA9IFQpICsgY29vcmRfZmxpcCgpCmBgYAoKV2UgY2FuIGFsc28gZmluZCBhbGwgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIG1hcmtpbmcgZWFjaCBjbHVzdGVyLiBUaGlzIG1heSB0YWtlIHNvbWUgdGltZS4KCmBgYHtyfQojY2x1c3QubWFya2VyczAgPC0gRmluZE1hcmtlcnMob2JqZWN0ID0gdGlzcywgaWRlbnQuMSA9IDAsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIHRocmVzaC51c2UgPSAwLjI1KQojdGlzcy5tYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IHRpc3MsIG9ubHkucG9zID0gVFJVRSwgbWluLnBjdCA9IDAuMjUsIHRocmVzaC51c2UgPSAwLjI1KQpgYGAKCkRpc3BsYXkgdGhlIHRvcCBtYXJrZXJzIHlvdSBjb21wdXRlZCBhYm92ZS4KYGBge3J9CiN0aXNzLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3Bfbig1LCBhdmdfbG9nRkMpCmBgYAoKVXNpbmcgdGhlIG1hcmtlcnMgYWJvdmUsIHdlIGNhbiBjb25maWRlbnRhbHkgbGFiZWwgbWFueSBvZiB0aGUgY2x1c3RlcnM6CgowOiBiZXRhCjM6IGFjaW5hcgo0OiBkdWN0YWwKNjogYmV0YQo3OiBlbmRvdGhlbGlhbAo4OiBpbW11bmUKOTogc3RlbGxhdGUKClRoZSBhYnVuZGFuY2Ugb2YgUHB5IGFuZCBHY2cgaW4gY2x1c3RlcnMgMSBhbmQgMiBtYWtlcyB0aGVtIHNlZW0gbGlrZSBtaXh0dXJlcyBvZiBhbHBoYSBhbmQgZ2FtbWEgY2VsbHMuIFRoZSBleHByZXNzaW9uIG9mIFNzdCBhbmQgSGhleCBpbiBjbHVzdGVyIDUKaW5kaWNhdGVzIHRoYXQgaXQgbWlnaHQgY29udGFpbiBtYW55IGRlbHRhIGNlbGxzLCBidXQgdG8gZ2V0IGEgZmluZXIgcmVzb2x1dGlvbiwgd2Ugc3Vic2V0IHRoZSBkYXRhIGFuZCByZWNvbXB1dGUuCgpXZSB3aWxsIGFkZCB0aG9zZSBjZWxsX29udG9sb2d5X2NsYXNzIHRvIHRoZSBkYXRhc2V0LgoKYGBge3J9CnRpc3MgPC0gU3Rhc2hJZGVudChvYmplY3QgPSB0aXNzLCBzYXZlLm5hbWUgPSAiY2x1c3Rlci5pZHMiKQoKY2x1c3Rlci5pZHMgPC0gYygwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5KQoKZnJlZV9hbm5vdGF0aW9uIDwtIGMoCiAgImJldGEgY2VsbCIsIAogICBOQSwgCiAgIE5BLCAKICAgImFjaW5hciBjZWxsIiwgCiAgICJkdWN0YWwgY2VsbCIsIAogICBOQSwKICAgImJldGEgY2VsbCIsIAogICAiZW5kb3RoZWxpYWwgY2VsbCIsIAogICAiaW1tdW5lIGNlbGwiLCAKICAgInN0ZWxsYXRlIGNlbGwiKQoKY2VsbF9vbnRvbG9neV9jbGFzcyA8LWMoCiAgInR5cGUgQiBwYW5jcmVhdGljIGNlbGwiLCAKICAgTkEsIAogICBOQSwgCiAgICJwYW5jcmVhdGljIGFjaW5hciBjZWxsIiwgCiAgICJwYW5jcmVhdGljIGR1Y3RhbCBjZWxsIiwgCiAgIE5BLCAKICAgInR5cGUgQiBwYW5jcmVhdGljIGNlbGwiLCAKICAgImVuZG90aGVsaWFsIGNlbGwiLCAKICAgImxldWtvY3l0ZSIsIAogICAicGFuY3JlYXRpYyBzdGVsbGF0ZSBjZWxsIikKCnZhbGlkYXRlX2NlbGxfb250b2xvZ3koY2VsbF9vbnRvbG9neV9jbGFzcykKY2VsbF9vbnRvbG9neV9pZCA9IGNvbnZlcnRfdG9fY2VsbF9vbnRvbG9neV9pZChjZWxsX29udG9sb2d5X2NsYXNzKQoKdGlzc0BtZXRhLmRhdGFbJ2ZyZWVfYW5ub3RhdGlvbiddIDwtIGFzLmNoYXJhY3RlcihwbHlyOjptYXB2YWx1ZXMoeCA9IHRpc3NAaWRlbnQsIGZyb20gPSBjbHVzdGVyLmlkcywgdG8gPSBmcmVlX2Fubm90YXRpb24pKQp2YWxpZGF0ZV9jZWxsX29udG9sb2d5KGNlbGxfb250b2xvZ3lfY2xhc3MpCmNlbGxfb250b2xvZ3lfaWQgPSBjb252ZXJ0X3RvX2NlbGxfb250b2xvZ3lfaWQoY2VsbF9vbnRvbG9neV9jbGFzcykKCnRpc3NAbWV0YS5kYXRhWydjZWxsX29udG9sb2d5X2NsYXNzJ10gPC0gYXMuY2hhcmFjdGVyKHBseXI6Om1hcHZhbHVlcyh4ID0gdGlzc0BpZGVudCwgZnJvbSA9IGNsdXN0ZXIuaWRzLCB0byA9IGNlbGxfb250b2xvZ3lfY2xhc3MpKQp0aXNzQG1ldGEuZGF0YVsnY2VsbF9vbnRvbG9neV9pZCddIDwtIGFzLmNoYXJhY3RlcihwbHlyOjptYXB2YWx1ZXMoeCA9IHRpc3NAaWRlbnQsIGZyb20gPSBjbHVzdGVyLmlkcywgdG8gPSBjZWxsX29udG9sb2d5X2lkKSkKYGBgCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKQ29sb3IgYnkgbWV0YWRhdGEsIGxpa2UgcGxhdGUgYmFyY29kZSwgdG8gY2hlY2sgZm9yIGJhdGNoIGVmZmVjdHMuCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSB0aXNzLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwbGF0ZS5iYXJjb2RlIikKYGBgCgojIyBTdWJjbHVzdGVyCgpgYGB7cn0Kc3VidGlzcyA9IFN1YnNldERhdGEodGlzcywgaWRlbnQudXNlID0gYygxLDIsNSkpCmBgYAoKYGBge3J9CnN1YnRpc3MgPC0gc3VidGlzcyAlPiUgU2NhbGVEYXRhKCkgJT4lIAogIEZpbmRWYXJpYWJsZUdlbmVzKGRvLnBsb3QgPSBUUlVFLCB4LmhpZ2guY3V0b2ZmID0gSW5mLCB5LmN1dG9mZiA9IDAuNSkgJT4lCiAgUnVuUENBKGRvLnByaW50ID0gRkFMU0UpCmBgYAoKYGBge3J9ClBDSGVhdG1hcChvYmplY3QgPSBzdWJ0aXNzLCBwYy51c2UgPSAxOjMsIGNlbGxzLnVzZSA9IDUwMCwgZG8uYmFsYW5jZWQgPSBUUlVFLCBsYWJlbC5jb2x1bW5zID0gRkFMU0UsIG51bS5nZW5lcyA9IDgpClBDRWxib3dQbG90KHN1YnRpc3MpCmBgYAoKCmBgYHtyfQpzdWIubi5wY3MgPSA4CnN1Yi5yZXMudXNlID0gMQpzdWJ0aXNzIDwtIHN1YnRpc3MgJT4lIEZpbmRDbHVzdGVycyhyZWR1Y3Rpb24udHlwZSA9ICJwY2EiLCBkaW1zLnVzZSA9IDE6c3ViLm4ucGNzLCAKICAgIHJlc29sdXRpb24gPSBzdWIucmVzLnVzZSwgcHJpbnQub3V0cHV0ID0gMCwgc2F2ZS5TTk4gPSBUUlVFKSAlPiUKICAgIFJ1blRTTkUoZGltcy51c2UgPSAxOnN1Yi5uLnBjcywgc2VlZC51c2UgPSAxMCwgcGVycGxleGl0eT0zMCkKClRTTkVQbG90KG9iamVjdCA9IHN1YnRpc3MsIGRvLmxhYmVsID0gVCwgcHQuc2l6ZSA9IDEuMiwgbGFiZWwuc2l6ZSA9IDQpCgpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9OH0KRmVhdHVyZVBsb3Qoc3VidGlzcywgZ2VuZXNfdG9fY2hlY2ssIG5Db2wgPSA1LCBjb2xzLnVzZSA9IGMoImdyZXkiLCAiYmx1ZSIpKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMH0KRG90UGxvdChzdWJ0aXNzLCBnZW5lc190b19jaGVjaywgY29sLm1heCA9IDIuNSwgcGxvdC5sZWdlbmQgPSBULCBkby5yZXR1cm4gPSBUKSArIGNvb3JkX2ZsaXAoKQpgYGAKCgpgYGB7cn0KVmxuUGxvdChzdWJ0aXNzLCAnUHB5JykKYGBgCgpgYGB7cn0KdGFibGUoc3VidGlzc0BpZGVudCkKYGBgCgpEaXNjb3ZlciBuZXcgUFAgbWFya2VyIGdlbmVzIChuZWdhdGl2ZSBvciBwb3NpdGl2ZSkKYGBge3J9CmdhbW1hX21hcmtlcnMgPSBGaW5kTWFya2VycyhzdWJ0aXNzLCBpZGVudC4xID0gYyg2LDcpLCBpZGVudC4yID0gYygwLDEsMiw0KSwgdGVzdC51c2UgPSAicm9jIikKYGBgCgpgYGB7cn0KZ2FtbWFfbWFya2VycyA9IEZpbmRNYXJrZXJzKHN1YnRpc3MsIGlkZW50LjEgPSBjKDYsNyksIGlkZW50LjIgPSBjKDAsMSwyLDQpLCB0ZXN0LnVzZSA9ICJ3aWxjb3giKQpgYGAKTmV3IG1hcmtlcnMgZnJvbSB0aGlzIHRlc3QgaW5jbHVkZQoxKSBuZWdhdGl2ZSBtYXJrZXIgZ2VuZXMsIGFrYS4gdGhvc2UgYWJzY2VudCBpbiBQUCBjZWxscyBvciBoaWdobHkgYWJ1bmRhbnQgaW4gYWxwaGEgY2VsbHMKJ0FyZzEnLCAnTWFmYicsICdHZnJhMycsICdTbGMzOGE1JywgJ0RwcDEwJywnQW5nJywnSXJ4MScsIAoyKSBwb3NpdGl2ZSBtYXJrZXIgZ2VuZXMsIGFrYS4gdGhvc2UgYWJzY2VudCBpbiBhbHBoYSBjZWxscyBvciBoaWdobHkgYWJ1bmRhbnQgaW4gUFAgY2VsbHMKJ0NkOScsICdTcHAxJywgJ1RzcGFuOCcsICdGb2xyMScsJ1ZzaWcxJwpgYGB7cn0KZ2FtbWFfZ2VuZXNfdG9fY2hlY2tfbmVnID0gYygnQXJnMScsICdNYWZiJywgJ0dmcmEzJywgJ1NsYzM4YTUnLCAnRHBwMTAnLCdBbmcnLCdJcngxJykKZ2FtbWFfZ2VuZXNfdG9fY2hlY2tfcG9zID0gYygnQ2Q5JywgJ1NwcDEnLCAnVHNwYW44JywgJ0ZvbHIxJywnVnNpZzEnKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTQsIGZpZy53aWR0aD04fQpGZWF0dXJlUGxvdChzdWJ0aXNzLCBnYW1tYV9nZW5lc190b19jaGVja19uZWcsIG5Db2wgPSA1LCBjb2xzLnVzZSA9IGMoImdyZXkiLCAiYmx1ZSIpKQpgYGAKCgpgYGB7cn0KRG90UGxvdChzdWJ0aXNzLCBnYW1tYV9nZW5lc190b19jaGVja19uZWcsIGNvbC5tYXggPSAyLjUsIHBsb3QubGVnZW5kID0gVCwgZG8ucmV0dXJuID0gVCkgKyBjb29yZF9mbGlwKCkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0yLCBmaWcud2lkdGg9OH0KRmVhdHVyZVBsb3Qoc3VidGlzcywgZ2FtbWFfZ2VuZXNfdG9fY2hlY2tfcG9zLCBuQ29sID0gNSwgY29scy51c2UgPSBjKCJncmV5IiwgImJsdWUiKSkKYGBgCgpgYGB7cn0KRG90UGxvdChzdWJ0aXNzLCBnYW1tYV9nZW5lc190b19jaGVja19wb3MsIGNvbC5tYXggPSAyLjUsIHBsb3QubGVnZW5kID0gVCwgZG8ucmV0dXJuID0gVCkgKyBjb29yZF9mbGlwKCkKYGBgCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD04fQpzdWJ0aXNzX2dlbmVzX3RvX2NoZWNrID0gYygnQ2hnYScsICdJc2wxJywgJ0djZycsICdNYWZiJywgJ0FyeCcsICdTc3QnLCAnSGhleCcsICdQZHgxJywgJ1BweScsJ0docmwnLCdHZnJhMycsICdTbGMzOGE1JywgJ0RwcDEwJywnQW5nJywnSXJ4MScsJ0NkOScsICdTcHAxJywgJ1RzcGFuOCcsICdGb2xyMScsJ1ZzaWcxJykKRmVhdHVyZVBsb3Qoc3VidGlzcywgc3VidGlzc19nZW5lc190b19jaGVjaywgbkNvbCA9IDUsIGNvbHMudXNlID0gYygiZ3JleSIsICJibHVlIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQpEb3RQbG90KHN1YnRpc3MsIHN1YnRpc3NfZ2VuZXNfdG9fY2hlY2ssIGNvbC5tYXggPSAyLjUsIHBsb3QubGVnZW5kID0gVCwgZG8ucmV0dXJuID0gVCkgKyBjb29yZF9mbGlwKCkKYGBgCgpGcm9tIHRoZXNlIGdlbmVzLCBpdCBhcHBlYXJzIHRoYXQgdGhlIGNsdXN0ZXJzIHJlcHJlc2VudDoKCjA6IGFscGhhCjE6IGFscGhhCjI6IGFscGhhCjM6IGRlbHRhCjQ6IGFscGhhCjU6IGRlbHRhCjY6IGdhbW1hCjc6IGdhbW1hCgpUaGUgbXVsdGl0dWRlIG9mIGNsdXN0ZXJzIG9mIGVhY2ggdHlwZSBjb3JyZXNwb25kIG1vc3RseSB0byBpbmRpdmlkdWFsIGFuaW1hbHMvc2V4ZXMuCgpgYGB7cn0KdGFibGUoRmV0Y2hEYXRhKHN1YnRpc3MsIGMoJ21vdXNlLmlkJywnaWRlbnQnKSkgJT4lIGRyb3BsZXZlbHMoKSkKYGBgCgpgYGB7cn0Kc3ViLmNsdXN0ZXIuaWRzIDwtIGMoMCwgMSwgMiwgMywgNCwgNSwgNiwgNykKc3ViLmZyZWVfYW5ub3RhdGlvbiA8LSBjKCJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEQgY2VsbCIsICJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEQgY2VsbCIsICJwYW5jcmVhdGljIFBQIGNlbGwiLCAicGFuY3JlYXRpYyBQUCBjZWxsIikKc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MgPC1jKCJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEQgY2VsbCIsICJwYW5jcmVhdGljIEEgY2VsbCIsICJwYW5jcmVhdGljIEQgY2VsbCIsICJwYW5jcmVhdGljIFBQIGNlbGwiLCAicGFuY3JlYXRpYyBQUCBjZWxsIikKCnZhbGlkYXRlX2NlbGxfb250b2xvZ3koc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MpCnN1Yi5jZWxsX29udG9sb2d5X2lkID0gY29udmVydF90b19jZWxsX29udG9sb2d5X2lkKHN1Yi5jZWxsX29udG9sb2d5X2NsYXNzKQoKc3VidGlzc0BtZXRhLmRhdGFbJ2ZyZWVfYW5ub3RhdGlvbiddIDwtIGFzLmNoYXJhY3RlcihwbHlyOjptYXB2YWx1ZXMoeCA9IHN1YnRpc3NAaWRlbnQsIGZyb20gPSBzdWIuY2x1c3Rlci5pZHMsIHRvID0gc3ViLmZyZWVfYW5ub3RhdGlvbikpCnZhbGlkYXRlX2NlbGxfb250b2xvZ3koc3ViLmNlbGxfb250b2xvZ3lfY2xhc3MpCnN1Yi5jZWxsX29udG9sb2d5X2lkID0gY29udmVydF90b19jZWxsX29udG9sb2d5X2lkKHN1Yi5jZWxsX29udG9sb2d5X2NsYXNzKQoKc3VidGlzc0BtZXRhLmRhdGFbJ2ZyZWVfYW5ub3RhdGlvbiddIDwtIGFzLmNoYXJhY3RlcihwbHlyOjptYXB2YWx1ZXMoeCA9IHN1YnRpc3NAaWRlbnQsIGZyb20gPSBzdWIuY2x1c3Rlci5pZHMsIHRvID0gc3ViLmZyZWVfYW5ub3RhdGlvbikpCnN1YnRpc3NAbWV0YS5kYXRhWydjZWxsX29udG9sb2d5X2NsYXNzJ10gPC0gYXMuY2hhcmFjdGVyKHBseXI6Om1hcHZhbHVlcyh4ID0gc3VidGlzc0BpZGVudCwgZnJvbSA9IHN1Yi5jbHVzdGVyLmlkcywgdG8gPSBzdWIuY2VsbF9vbnRvbG9neV9jbGFzcykpCnN1YnRpc3NAbWV0YS5kYXRhWydjZWxsX29udG9sb2d5X2lkJ10gPC0gYXMuY2hhcmFjdGVyKHBseXI6Om1hcHZhbHVlcyh4ID0gc3VidGlzc0BpZGVudCwgZnJvbSA9IHN1Yi5jbHVzdGVyLmlkcywgdG8gPSBzdWIuY2VsbF9vbnRvbG9neV9pZCkpCmBgYAoKIyMgQWRkIHN1YmNsdXN0ZXIgY2VsbF9vbnRvbG9neV9jbGFzcyB0byBtYWluIGNlbGxfb250b2xvZ3lfY2xhc3MKCmBgYHtyfQpzdWIuY2VsbHMgPSByb3duYW1lcyhzdWJ0aXNzQG1ldGEuZGF0YSkKCnRpc3NAbWV0YS5kYXRhW3N1Yi5jZWxscywgJ2ZyZWVfYW5ub3RhdGlvbiddID0gc3VidGlzc0BtZXRhLmRhdGFbLCdmcmVlX2Fubm90YXRpb24nXQp0aXNzQG1ldGEuZGF0YVtzdWIuY2VsbHMsICdjZWxsX29udG9sb2d5X2NsYXNzJ10gPSBzdWJ0aXNzQG1ldGEuZGF0YVssJ2NlbGxfb250b2xvZ3lfY2xhc3MnXQp0aXNzQG1ldGEuZGF0YVtzdWIuY2VsbHMsICdjZWxsX29udG9sb2d5X2lkJ10gPSBzdWJ0aXNzQG1ldGEuZGF0YVssJ2NlbGxfb250b2xvZ3lfaWQnXQpgYGAKCgojIyBDaGVja2luZyBmb3IgYmF0Y2ggZWZmZWN0cwoKQ29sb3IgYnkgbWV0YWRhdGEsIGxpa2UgcGxhdGUgYmFyY29kZSwgdG8gY2hlY2sgZm9yIGJhdGNoIGVmZmVjdHMuCmBgYHtyfQpUU05FUGxvdChvYmplY3QgPSB0aXNzLCBkby5yZXR1cm4gPSBUUlVFLCBncm91cC5ieSA9ICJwbGF0ZS5iYXJjb2RlIikKYGBgCgojIEZpbmFsIGNvbG9yaW5nCgpDb2xvciBieSBjZWxsIG9udG9sb2d5IGNsYXNzIG9uIHRoZSBvcmlnaW5hbCBUU05FLgoKYGBge3J9ClRTTkVQbG90KG9iamVjdCA9IHRpc3MsIGRvLnJldHVybiA9IFRSVUUsIGdyb3VwLmJ5ID0gImNlbGxfb250b2xvZ3lfY2xhc3MiKQp0YWJsZSh0aXNzQG1ldGEuZGF0YVtbImNlbGxfb250b2xvZ3lfY2xhc3MiXV0pCmBgYAoKIyBTYXZlIHRoZSBSb2JqZWN0IGZvciBsYXRlcgoKYGBge3J9CmZpbGVuYW1lID0gaGVyZSgnMDBfZGF0YV9pbmdlc3QnLCAnMDRfdGlzc3VlX3JvYmpfZ2VuZXJhdGVkJywgCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiZmFjc18iLCB0aXNzdWVfb2ZfaW50ZXJlc3QsICJfc2V1cmF0X3Rpc3MuUm9iaiIpKQpwcmludChmaWxlbmFtZSkKc2F2ZSh0aXNzLCBmaWxlPWZpbGVuYW1lKQpgYGAKCmBgYHtyfQojIFRvIHJlbG9hZCBhIHNhdmVkIG9iamVjdAojIGZpbGVuYW1lID0gaGVyZSgnMDBfZGF0YV9pbmdlc3QnLCAnMDRfdGlzc3VlX3JvYmpfZ2VuZXJhdGVkJywgCiMgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJmYWNzXyIsIHRpc3N1ZV9vZl9pbnRlcmVzdCwgIl9zZXVyYXRfdGlzcy5Sb2JqIikpCiMgbG9hZChmaWxlPWZpbGVuYW1lKQpgYGAKCiMjIEFkZCBjb2x1bW4gZm9yIE5ldXJvZzMgZXhwcmVzc2lvbiBmb3Igc3VwcGxlbWVudGFsIGZpZ3VyZXMKCmBgYHtyfQp0aXNzQG1ldGEuZGF0YVssICdOZXVyb2czPjBfc2NhbGVkJ10gPSBGZXRjaERhdGEodGlzcywgYygiTmV1cm9nMyIpLCB1c2UucmF3PUZBTFNFKSA+IDAKdGlzc0BtZXRhLmRhdGFbLCAnTmV1cm9nMz4wX3JhdyddID0gRmV0Y2hEYXRhKHRpc3MsIGMoIk5ldXJvZzMiKSwgdXNlLnJhdz1UUlVFKSA+IDAKYWRkaXRpb25hbF9jb2xzID0gYygnTmV1cm9nMz4wX3NjYWxlZCcsICdOZXVyb2czPjBfcmF3JykKYGBgCgoKIyBFeHBvcnQgdGhlIGZpbmFsIG1ldGFkYXRhCgpTbyB0aGF0IEJpb2h1YiBjYW4gZWFzaWx5IGNvbWJpbmUgYWxsIHlvdXIgY2VsbF9vbnRvbG9neV9jbGFzcywgcGxlYXNlIGV4cG9ydCB0aGVtIGFzIGEgc2ltcGxlIGNzdi4KCmBgYHtyfQpoZWFkKHRpc3NAbWV0YS5kYXRhKQpgYGAKCmBgYHtyfQpmaWxlbmFtZSA9IGhlcmUoJzAwX2RhdGFfaW5nZXN0JywgJzAzX3Rpc3N1ZV9hbm5vdGF0aW9uX2NzdicsIAogICAgICAgICAgICAgICAgICAgICBwYXN0ZTAodGlzc3VlX29mX2ludGVyZXN0LCAiX2Fubm90YXRpb24uY3N2IikpCndyaXRlLmNzdihGZXRjaERhdGEodGlzcywgYygncGxhdGUuYmFyY29kZScsJ2NlbGxfb250b2xvZ3lfY2xhc3MnLCdjZWxsX29udG9sb2d5X2lkJywgJ2ZyZWVfYW5ub3RhdGlvbicsICd0U05FXzEnLCAndFNORV8yJykpLCBmaWxlPWZpbGVuYW1lKQpgYGAKCgojIEV4cGxvcmUgUHB5KyBtdWx0aWhvcm1vbmFsIGNlbGxzICh0byBiZSBjb250aW51ZWQpCgoKYGBge3J9CkZldGNoRGF0YShzdWJ0aXNzLCBjKCdQcHknLCAnR2NnJywgJ0FyeCcsICdJcngyJywgJ01hZmInLCAnbW91c2UuaWQnLCAncGxhdGUuYmFyY29kZScsICdpZGVudCcpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHB5LCB5ID0gR2NnLCBjb2xvciA9IHBsYXRlLmJhcmNvZGUpKSArIGdlb21fcG9pbnQoKQojIEl0IHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIGZldGNoIHRoZSBpZHMgb2YgdGhlc2UgY2VsbHMgZXhwcmVzc2luZyBoaWdoIEdjZyBhcyB3ZWxsIGFzIFBweSwgYW5kIGV4YW1pbmUgdGhlaXIgZ2VuZXRpYyBzaWduYXR1cmUuCmBgYAoKCmBgYHtyfQpnYW1tYXRpc3MgPC0gUnVuUENBKHN1YnRpc3MsIHBjLmdlbmVzID0gYygnQXJnMScsICdNYWZiJywgJ0dmcmEzJywgJ1NsYzM4YTUnLCAnRHBwMTAnLCdBbmcnLCdJcngxJywgJ0NkOScsICdTcHAxJywgJ1RzcGFuOCcsICdGb2xyMScsJ1ZzaWcxJyksIHBjcy5jb21wdXRlID0gMykKYGBgCgpgYGB7cn0KUENIZWF0bWFwKG9iamVjdCA9IGdhbW1hdGlzcywgcGMudXNlID0gMTozLCBjZWxscy51c2UgPSA1MDAsIGRvLmJhbGFuY2VkID0gVFJVRSwgbGFiZWwuY29sdW1ucyA9IEZBTFNFLCBudW0uZ2VuZXMgPSA4KQpgYGAKCmBgYHtyfQpHZW5lUGxvdChzdWJ0aXNzLCAnVnNpZzEnLCAnR2ZyYTMnKQpgYGAKCldyaXRlIHRoZSBjZWxsIG9udG9sb2d5IGFuZCBmcmVlIGFubm90YXRpb25zIHRvIENTVi4KCmBgYHtyfQpzYXZlX2Fubm90YXRpb25fY3N2KHRpc3MsIHRpc3N1ZV9vZl9pbnRlcmVzdCwgImZhY3MiLCBhZGRpdGlvbmFsX2NvbHMgPSBhZGRpdGlvbmFsX2NvbHMpCmBgYAo=